package com.ehsy.comtroller;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Map;

/**
 * @author YanZhen_Li
 * @version 1.0
 * @title FileController
 * @description
 * @create 2024/6/17 19:03
 */
@Controller
@RequestMapping("/file")
public class FileController {
    @PostMapping(value = "/testFile1/{fileName}", produces = "application/octet-stream")
    public ResponseEntity<String> convertByteToString(@RequestBody byte[] file, @PathVariable("fileName") String fileName) {
        // 将上传的文件（字节流）转换为字符串
        String content = new String(file, StandardCharsets.UTF_8);
        return ResponseEntity.ok("文件名是：" + fileName + "，文件内容是：" + content);
    }
    @PostMapping(value = "/testFile", produces = "multipart/form-data")
    public ResponseEntity<String> convertByteStreamToString(@RequestParam("file") MultipartFile file) {
        try {
            // 将上传的文件（字节流）转换为字符串
            byte[] bytes = file.getBytes();
            String content = new String(bytes, StandardCharsets.UTF_8);
            String name = file.getOriginalFilename();
            return ResponseEntity.ok("文件名是：" + name + "，文件内容是：" + content);
        } catch (IOException e) {
            // 处理文件读取或转换过程中的异常
            throw new MultipartException("Failed to convert byte stream to string", e);
        }
    }

    @PostMapping(value = "/testFileAndParam", produces = "multipart/form-data")
    public ResponseEntity<String> convertByteStreamToStringAndParam(@RequestParam("file") MultipartFile file, @RequestParam(required = false) Map<String, Object> params) {
        try {
            // 将上传的文件（字节流）转换为字符串
            byte[] bytes = file.getBytes();
            String content = new String(bytes, StandardCharsets.UTF_8);
            String name = file.getOriginalFilename();
            return ResponseEntity.ok("参数有："+ params +"文件名是：" + name + "，文件内容是：" + content);
        } catch (IOException e) {
            // 处理文件读取或转换过程中的异常
            throw new MultipartException("Failed to convert byte stream to string", e);
        }
    }

    @GetMapping("/download/{fileName:.+}")
    public void downloadWithControlledSpeed(@PathVariable String fileName, HttpServletResponse response) {
        try {
            Resource resource = new ClassPathResource(fileName);

            if (!resource.exists()) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 设置响应头
            response.setHeader(HttpHeaders.CONTENT_LENGTH, Long.toString(resource.contentLength()));
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

            // 控制下载限制为每秒500KB
            long bytesPerSecond = 500 * 1024; // 500KB/s
            long startTime = Instant.now().toEpochMilli();

            InputStream inputStream = resource.getInputStream();
            OutputStream outputStream = response.getOutputStream();

            byte[] buffer = new byte[1024];
            int totalBytes = 0;
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                totalBytes += bytesRead;
                outputStream.write(buffer, 0, bytesRead);

                // 简单的速率控制逻辑，非精确控制，仅作示例
                long currentTime = Instant.now().toEpochMilli();
                long elapsedTime = currentTime - startTime + 1;
                if (elapsedTime >= 10) { // 文件太小了，一不留神就传送完了，所以每10毫秒检查一次
                    long bytesSentThisSecond = totalBytes / elapsedTime; // 当前每毫秒发送了多少字节
                    if (bytesSentThisSecond > bytesPerSecond / 1000) {
                        long multipleSending = totalBytes - bytesPerSecond * elapsedTime / 1000;
                        Thread.sleep(1000 * multipleSending / bytesPerSecond); // 等待，以控制速率
                    }
                }
            }

            outputStream.flush();
            outputStream.close();
            inputStream.close();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

}
